/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "codec_node.h"
// #include "MemDmabuf2.h"
// #include "colorfunc.h"
#include <securec.h>
#include "v4l2_client.h"
#include "jpeg_api.h"
#include <dlfcn.h>
#include <time.h>
#include "vdi_types.h"
// extern "C" {
// #include <jpeglib.h>
// #include <transupp.h>
// }
namespace OHOS::Camera {
AvcH264EncInterface* CodecNode::CreateAvcH264EncInterface()
{
    void *handler = dlopen("/vendor/soc_platform/lib64/libsprd_h264enc_wrapper.z.so", RTLD_LAZY);
    if (handler == nullptr) {
        CAMERA_LOGE("failed to dlopen  /vendor/soc_platform/lib64/libsprd_h264enc_wrapper.z.so, %{public}s", dlerror());
        return nullptr;
    }

    typedef AvcH264EncInterface* CreateInstanceFunc();
    CreateInstanceFunc* createInstance = (CreateInstanceFunc*) dlsym(handler, "CreateAvcH264Encoder");
    if (createInstance == nullptr) {
        const char* dlsym_error = dlerror();
        if (dlsym_error) {
            CAMERA_LOGE("Cannot load symbol CreateAvcH264Encoder, %{public}s, %{public}p", dlsym_error, createInstance);
        }
        CAMERA_LOGD("load symbol CreateAvcH264Encoder, %{public}p", createInstance);
        return nullptr;
    }
 
    // 使用动态库中的函数创建对象并调用方法
    AvcH264EncInterface* H264EncHandle = createInstance();
    if (H264EncHandle == nullptr) {
        CAMERA_LOGE("CreateAvcH264EncAdapterInstance, failed");
    }
 
    // 关闭动态库
    // dlclose(handle);
    h264Handle = handler;
    return H264EncHandle;
}

CodecNode::CodecNode(const std::string& name, const std::string& type, const std::string &cameraId) : NodeBase(name, type, cameraId)
{
    if (bufferRotate_ != NULL) {
        free(bufferRotate_) ;
        bufferRotate_ = NULL;
    }
    h264Encoder = CodecNode::CreateAvcH264EncInterface();
    CAMERA_LOGV("%{public}s enter, type(%{public}s)\n", name_.c_str(), type_.c_str());
}

CodecNode::~CodecNode()
{
    if (bufferRotate_ != NULL) {
        free(bufferRotate_) ;
        bufferRotate_ = NULL;
    }
    if (h264Handle != nullptr) {
        dlclose(h264Handle);
        h264Handle = nullptr;
    }
    startflag = 0;
    CAMERA_LOGI("~CodecNode Node exit.");
}

RetCode CodecNode::Start(const int32_t streamId)
{
    CAMERA_LOGI("RKCodecNode::Start streamId = %{public}d\n", streamId);
    uint64_t bufferPoolId = 0;
    startflag = 0;

    outPutPorts_ = GetOutPorts();
    for (auto& out : outPutPorts_) {
        bufferPoolId = out->format_.bufferPoolId_;
    }

    BufferManager* bufferManager = Camera::BufferManager::GetInstance();
    if (bufferManager == nullptr) {
        CAMERA_LOGE("scale buffer get instance failed");
        return RC_ERROR;
    }

    bufferPool_ = bufferManager->GetBufferPool(bufferPoolId);
    if (bufferPool_ == nullptr) {
        CAMERA_LOGE("get bufferpool failed: %{public}zu", bufferPoolId);
        return RC_ERROR;
    }
    if (bufferRotate_ != NULL) {
        free(bufferRotate_) ;
        bufferRotate_ = NULL;
    }
    return RC_OK;
}

RetCode CodecNode::Stop(const int32_t streamId)
{
    CAMERA_LOGI("CodecNode::Stop streamId = %{public}d\n", streamId);
    startflag = 0;
    // status = START;
    if (bufferRotate_ != NULL) {
        free(bufferRotate_) ;
        bufferRotate_ = NULL;
    }
    return RC_OK;
}

RetCode CodecNode::Flush(const int32_t streamId)
{
    CAMERA_LOGI("CodecNode::Flush streamId = %{public}d\n", streamId);
    return RC_OK;
}

// static void RotJpegImg(
//     const unsigned char *inputImg, size_t inputSize, unsigned char **outImg, size_t *outSize, JXFORM_CODE rotDegrees)
// {
//     struct jpeg_decompress_struct inputInfo;
//     struct jpeg_error_mgr jerrIn;
//     struct jpeg_compress_struct outInfo;
//     struct jpeg_error_mgr jerrOut;
//     jvirt_barray_ptr *src_coef_arrays;
//     jvirt_barray_ptr *dst_coef_arrays;

//     inputInfo.err = jpeg_std_error(&jerrIn);
//     jpeg_create_decompress(&inputInfo);
//     outInfo.err = jpeg_std_error(&jerrOut);
//     jpeg_create_compress(&outInfo);
//     jpeg_mem_src(&inputInfo, inputImg, inputSize);
//     jpeg_mem_dest(&outInfo, outImg, (unsigned long *)outSize);

//     JCOPY_OPTION copyoption;
//     jpeg_transform_info transformoption;
//     transformoption.transform = rotDegrees;
//     transformoption.perfect = TRUE;
//     transformoption.trim = FALSE;
//     transformoption.force_grayscale = FALSE;
//     transformoption.crop = FALSE;

//     jcopy_markers_setup(&inputInfo, copyoption);
//     (void)jpeg_read_header(&inputInfo, TRUE);

//     if (!jtransform_request_workspace(&inputInfo, &transformoption)) {
//         CAMERA_LOGE("%{public}s: transformation is not perfect", __func__);
//         return;
//     }

//     src_coef_arrays = jpeg_read_coefficients(&inputInfo);
//     jpeg_copy_critical_parameters(&inputInfo, &outInfo);
//     dst_coef_arrays = jtransform_adjust_parameters(&inputInfo, &outInfo, src_coef_arrays, &transformoption);
//     jpeg_write_coefficients(&outInfo, dst_coef_arrays);
//     jcopy_markers_execute(&inputInfo, &outInfo, copyoption);
//     jtransform_execute_transformation(&inputInfo, &outInfo, src_coef_arrays, &transformoption);

//     jpeg_finish_compress(&outInfo);
//     jpeg_destroy_compress(&outInfo);
//     (void)jpeg_finish_decompress(&inputInfo);
//     jpeg_destroy_decompress(&inputInfo);
// }

// void CodecNode::encodeJpegToMemory(unsigned char* image, int width, int height,
//     const char* comment, unsigned long* jpegSize, unsigned char** jpegBuf)
// {
//     struct jpeg_compress_struct cInfo;
//     struct jpeg_error_mgr jErr;
//     JSAMPROW row_pointer[1];
//     int row_stride = 0;
//     constexpr uint32_t colorMap = 3;
//     constexpr uint32_t compressionRatio = 100;
//     constexpr uint32_t pixelsThick = 3;

//     cInfo.err = jpeg_std_error(&jErr);

//     jpeg_create_compress(&cInfo);
//     cInfo.image_width = width;
//     cInfo.image_height = height;
//     cInfo.input_components = colorMap;
//     cInfo.in_color_space = JCS_RGB;

//     jpeg_set_defaults(&cInfo);
//     jpeg_set_quality(&cInfo, compressionRatio, TRUE);
//     jpeg_mem_dest(&cInfo, jpegBuf, jpegSize);
//     jpeg_start_compress(&cInfo, TRUE);

//     if (comment) {
//         jpeg_write_marker(&cInfo, JPEG_COM, (const JOCTET*)comment, strlen(comment));
//     }

//     row_stride = width;
//     while (cInfo.next_scanline < cInfo.image_height) {
//         row_pointer[0] = &image[cInfo.next_scanline * row_stride * pixelsThick];
//         jpeg_write_scanlines(&cInfo, row_pointer, 1);
//     }

//     jpeg_finish_compress(&cInfo);
//     jpeg_destroy_compress(&cInfo);

//     size_t rotJpgSize = 0;
//     unsigned char* rotJpgBuf = nullptr;
//     /* rotate image */
//     RotJpegImg(*jpegBuf, *jpegSize, &rotJpgBuf, &rotJpgSize, JXFORM_ROT_270);
//     if (rotJpgBuf != nullptr && rotJpgSize != 0) {
//         free(*jpegBuf);
//         *jpegBuf = rotJpgBuf;
//         *jpegSize = rotJpgSize;
//     }
// }

unsigned char CodecNode::Clip(int value) {
    return (unsigned char)(value > 255 ? 255 : value < 0 ? 0 : value);
}

void CodecNode::YUVToRGB(int Y, int U, int V, unsigned char* Red, unsigned char* Green, unsigned char* Blue, unsigned char*Alapha)
{
    /*
    *Red   = ((Y << 8) + ((V << 8) + (V << 5) + (V << 2))) >> 8;
    *Green = ((Y << 8) - ((U << 6) + (U << 5) + (U << 2)) - ((V << 7) + (V << 4) + (V << 2) + V)) >> 8;
    *Blue = ((Y << 8) + (U << 9) + (U << 3)) >> 8;
    */

    int r = 1.164 * (Y - 16) + 2.018 * (U - 128);
    int g =  1.164 * (Y - 16) + 0.813 * (V - 128) - 0.391 * (U - 128);
    int b = 1.164 * (Y - 16) + 1.596 * (V - 128);
    *Red = Clip(r);
    *Green = Clip(g);
    *Blue = Clip(b);
    *Alapha = 255;
};

/*void CodecNode::YuvBufferToRGBA8888(void *src1, unsigned char *dst, int width, int height)
{
    // static int Tabv1[256] = { -180, -179, -177, -176, -174, -173, -172, -170, -169, -167, -166, -165, -163, -162, -160, -159, -158, -156, -155, -153, -152, -151, -149, -148, -146, -145, -144, -142, -141, -139, -138, -137,  -135, -134, -132, -131, -130, -128, -127, -125, -124, -123, -121, -120, -118, -117, -115, -114, -113, -111, -110, -108, -107, -106, -104, -103, -101, -100, -99, -97, -96, -94, -93, -92, -90,  -89, -87, -86, -85, -83, -82, -80, -79, -78, -76, -75, -73, -72, -71, -69, -68, -66, -65, -64,-62, -61, -59, -58, -57, -55, -54, -52, -51, -50, -48, -47, -45, -44, -43, -41, -40, -38, -37,  -36, -34, -33, -31, -30, -29, -27, -26, -24, -23, -22, -20, -19, -17, -16, -15, -13, -12, -10, -9, -8, -6, -5, -3, -2, 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 70, 71, 72, 74, 75, 77, 78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 136, 137, 138, 140, 141, 143, 144, 145, 147, 148,  150, 151, 152, 154, 155, 157, 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 173, 175, 176, 178 };
    // static int Tabv2[256] = { -92, -91, -91, -90, -89, -88, -88, -87, -86, -86, -85, -84, -83, -83, -82, -81, -81, -80, -79, -78, -78, -77, -76, -76, -75, -74, -73, -73, -72, -71, -71, -70, -69, -68, -68, -67, -66, -66, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -53, -53, -52, -51, -51, -50, -49, -48, -48, -47, -46, -46, -45, -44, -43, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -36, -35, -34, -33, -33, -32, -31, -31, -30, -29, -28, -28, -27, -26, -26, -25, -24, -23, -23, -22, -21, -21, -20, -19, -18, -18, -17, -16, -16, -15, -14, -13, -13, -12, -11, -11, -10, -9, -8, -8, -7, -6, -6, -5, -4, -3, -3, -2, -1, 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60, 60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 72, 73, 74, 75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 90 };
    // static int Tabu1[256] = { -44, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -39, -39, -39, -38, -38, -38, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -33, -33, -33, -32, -32, -32, -31, -31, -31, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24, -24, -23, -23, -22, -22, -22, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43 };
    // static int Tabu2[256] = { -227, -226, -224, -222, -220, -219, -217, -215, -213, -212, -210, -208, -206, -204, -203, -201, -199, -197, -196, -194, -192, -190, -188, -187, -185, -183, -181, -180, -178, -176, -174, -173, -171, -169, -167, -165, -164, -162, -160, -158, -157, -155, -153, -151, -149, -148, -146, -144, -142, -141, -139, -137, -135, -134, -132, -130, -128, -126, -125, -123, -121, -119, -118, -116, -114, -112, -110, -109, -107, -105, -103, -102, -100, -98, -96, -94, -93, -91, -89, -87, -86, -84, -82, -80, -79, -77, -75, -73, -71, -70, -68, -66, -64, -63, -61, -59, -57, -55, -54, -52, -50, -48, -47, -45, -43, -41, -40, -38, -36, -34, -32, -31, -29, -27, -25, -24, -22, -20, -18, -16, -15, -13, -11, -9, -8, -6, -4, -2, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 17, 19, 21, 23, 24, 26, 28, 30, 31, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102, 104, 106, 108, 109, 111, 113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131, 133, 134, 136, 138, 140, 141, 143, 145, 147, 148, 150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 187, 189, 191, 193, 195, 196, 198, 200, 202, 203, 205, 207, 209, 211, 212, 214, 216, 218, 219, 221, 223, 225 };
    // if (width < 1 || height < 1 || src1 == NULL || dst == NULL)
    //     return ;
    // const long len = width * height;
    // unsigned char* yItem = (unsigned char *)src1;
    // unsigned char* vItem = &yItem[len];
    // unsigned char* uItem = &vItem[len >> 2];

    // int rgb[3];
    // int yIdx,uIdx,vIdx,idx;
    // int rdif,invgdif,bdif;
    // for (int i = 0;i < height;i++){
    //     for (int j = 0;j < width;j++){
    //         yIdx = i * width + j;
    //         vIdx = (i/2) * (width/2) + (j/2);
    //         uIdx = vIdx;

    //         rdif = Tabv1[vItem[vIdx]];
    //         invgdif = Tabu1[uItem[uIdx]] + Tabv2[vItem[vIdx]];
    //         bdif = Tabu2[uItem[uIdx]];

    //         rgb[0] = yItem[yIdx] + bdif;
    //         rgb[1] = yItem[yIdx] - invgdif;
    //         rgb[2] = yItem[yIdx] + rdif;
    //         int index = (i * width + j) * 4;
    //         for (int k = 0;k < 3;k++){
    //             idx = index + k;
    //             if(rgb[k] >= 0 && rgb[k] <= 255)
    //                 dst[idx] = rgb[k];
    //             else
    //                 dst[idx] = (rgb[k] < 0)?0:255;
    //         }
    //         dst[index + 3] = 255;
    //     }
    // }

    unsigned char * src = (unsigned char *)src1;
    /*YUV420_I420(YUV420_YU12)
    int ustart = width * height;
    int vstart = ustart + ustart / 4;
    int temp = 0;
    int offset = 0;
    for (int i = 0; i < height; i++) {
        for (int j = 0;j < width; j++) {
            temp = (i * width + j);
            offset = (i /2) * (width / 2) + j / 2;
            YUVToRGB(*(src + temp), *(src + ustart + offset), *(src + vstart + offset), 
                (dst + temp * 4), (dst + (temp * 4 + 1)),  (dst + (temp * 4 + 2)),  (dst + (temp * 4 + 3)));
        }
    }*/
    /*YUV420_YV12
    int vstart = width * height;
    int ustart = ustart + ustart / 4;
    int temp = 0;
    int offset = 0;
    for (int i = 0; i < height; i++) {
        for (int j = 0;j < width; j++) {
            temp = (i * width + j);
            offset = (i /2) * (width / 2) + j / 2;
            YUVToRGB(*(src + temp), *(src + ustart + offset), *(src + vstart + offset), 
                (dst + temp * 4), (dst + (temp * 4 + 1)),  (dst + (temp * 4 + 2)),  (dst + (temp * 4 + 3)));
        }
    }*/
    /*YUV420_NV12*/
    // int ustart = width * height;
    // int temp = 0;
    // int offset = 0;
    // for (int i = 0; i < height; i++) {
    //     for (int j = 0;j < width; j++) {
    //         temp = (i * width + j);
    //         offset = (i /2) * (width / 2) + j / 2;
    //         YUVToRGB(*(src + temp), *(src + ustart + offset * 2), *(src + ustart + offset * 2 + 1), 
    //             (dst + temp * 4), (dst + (temp * 4 + 1)),  (dst + (temp * 4 + 2)),  (dst + (temp * 4 + 3)));
    //     }
    // }
     /*YUV420_NV21*/
    // int ustart = width * height;
    // int temp = 0;
    // int offset = 0;
    // for (int i = 0; i < height; i++) {
    //     for (int j = 0;j < width; j++) {
    //         temp = (i * width + j);
    //         offset = (i /2) * (width / 2) + j / 2;
    //         YUVToRGB(*(src + temp), *(src + ustart + offset * 2 + 1), *(src + ustart + offset * 2), 
    //             (dst + temp * 4), (dst + (temp * 4 + 1)),  (dst + (temp * 4 + 2)),  (dst + (temp * 4 + 3)));
    //     }
    // }
// }*/

/*void CodecNode::Yuv420SwToRGBA8888(std::shared_ptr<IBuffer>& buffer)
{
    // CAMERA_LOGI("CodecNode::Yuv420SwToRGBA8888 enter");
    // constexpr uint32_t RgbaWidth = 4;
    // if (buffer == nullptr) {
    //     CAMERA_LOGI("CodecNode::Yuv420SwToRGBA8888 buffer == nullptr");
    //     return ;
    // }

    // if ((previewWidth_ != buffer->GetWidth()) || (previewHeight_ != buffer->GetHeight())) {
    //     previewWidth_ = buffer->GetWidth();
    //     previewHeight_ = buffer->GetHeight();
    //     if (previewTempBuff_ != nullptr) {
    //         free(previewTempBuff_);
    //         previewTempBuff_ = nullptr;
    //     }
    //     if ((previewWidth_ <= 0) || (previewHeight_ <= 0)) {
    //         CAMERA_LOGI("CodecNode::  buffer,Width Height Invalid");
    //         return ;
    //     } 
    //     size_t rgbaSize = previewWidth_ * previewHeight_ * RgbaWidth;
    //     previewTempBuff_ = (unsigned char *)malloc(rgbaSize);
    //     if (previewTempBuff_ == nullptr) {
    //         CAMERA_LOGI("CodecNode::Yuv420SwToRGBA8888 malloc buffer == nullptr");
    //         return ;
    //     }
    //     rgbaSize_ = rgbaSize;
    // } else {
    //     if (previewTempBuff_ == nullptr) {
    //         if (rgbaSize_ > 0) {
    //             previewTempBuff_ = (unsigned char *)malloc(rgbaSize_);
    //             if (previewTempBuff_ == nullptr) {
    //                 CAMERA_LOGI("CodecNode::Yuv420SwToRGBA8888 malloc buffer == nullptr");
    //                 return ;
    //             }
    //         } else {
    //             previewWidth_ = 0;
    //             previewHeight_ = 0;
    //             return ;
    //         }
    //     }
    // }

    // YuvBufferToRGBA8888(buffer->GetVirAddress(), previewTempBuff_, previewWidth_, previewHeight_);

    // int ret = memcpy_s((unsigned char*)buffer->GetVirAddress(), rgbaSize_, previewTempBuff_, rgbaSize_);
    // if (ret == 0) {
    //     // buffer->SetSize(rgbaSize);
    //     buffer->SetEsFrameSize(rgbaSize_);
    // } else {
    //     buffer->SetEsFrameSize(0);
    //     CAMERA_LOGI("CodecNode::Yuv420SwToRGBA8888 memcpy_s buffer  fail");
    // }

    // if (stopFlag_ == 1 && previewTempBuff_ != nullptr) {
    //     free(previewTempBuff_);
    //     previewTempBuff_ = nullptr;
    // }
    // return;
}*/

/*void CodecNode::YUV420ToRGBA8888WithNeon(std::shared_ptr<IBuffer>& buffer)
{
    CAMERA_LOGI("CodecNode::YUV420ToRGBA8888WithNeon enter");
    constexpr uint32_t RgbaWidth = 4;
    if (buffer == nullptr) {
        CAMERA_LOGI("CodecNode::YUV420ToRGBA8888WithNeon buffer == nullptr");
        return ;
    }
    previewWidth_ = buffer->GetWidth();
    previewHeight_ = buffer->GetHeight();

    if ((previewWidth_ <= 0) || (previewHeight_ <= 0)) {
        CAMERA_LOGI("CodecNode::  buffer,Width Height Invalid");
        return ;
    }
    size_t rgbaSize = previewWidth_ * previewHeight_ * RgbaWidth;
    unsigned char *temp = (unsigned char *)malloc(rgbaSize);
    if (temp == nullptr) {
        CAMERA_LOGI("CodecNode::YUV420ToRGBA8888WithNeon malloc buffer == nullptr");
        return ;
    }
    //ConvertToRGBAWithNeon((unsigned char*)buffer->GetVirAddress(), (int)previewWidth_, (int)previewHeight_, (int*)temp);
    int ret = memcpy_s((unsigned char*)buffer->GetVirAddress(), rgbaSize, temp, rgbaSize);
    if (ret == 0) {
        buffer->SetSize(rgbaSize);
        buffer->SetEsFrameSize(rgbaSize);
    } else {
        buffer->SetEsFrameSize(0);
        CAMERA_LOGI("CodecNode::YUV420ToRGBA8888WithNeon memcpy_s buffer  fail");
    }

    free(temp);
    // if (stopFlag_ == 1) {
    //      if (previewTempBuff_ != nullptr) {
    //         CAMERA_LOGE("CodecNode::YUV420ToRGBA8888WithNeon a stopFlag_ = 1");
    //         free(previewTempBuff_);
    //         previewTempBuff_ = nullptr;
    //      }
    //      return;
    // }
    // uint32_t previewWidth = buffer->GetWidth();
    // uint32_t previewHeight = buffer->GetHeight();
    // if ((previewWidth <= 0) || (previewHeight <= 0)) {
    //     CAMERA_LOGE("CodecNode::YUV420ToRGBA8888WithNeon Width or Height == 0");
    //     return;
    // }
    // constexpr uint32_t RgbaWidth = 4;
    // rgbaSize_ = previewWidth * previewHeight * RgbaWidth;
    // previewTempBuff_ = (unsigned char *)malloc(rgbaSize_);
    // if (previewTempBuff_ == nullptr) {
    //     CAMERA_LOGE("CodecNode::YUV420ToRGBA8888WithNeon a Width = %{public}zu or Height = %{public}zu previewTempBuff_ = null", previewWidth_, previewHeight_);
    //     return;
    // }
    // ConvertToRGBAWithNeon((unsigned char*)buffer->GetVirAddress(), (int)previewWidth, (int)previewHeight, (int*)previewTempBuff_);
    // int ret = memcpy_s((unsigned char*)buffer->GetVirAddress(), rgbaSize_, previewTempBuff_, rgbaSize_);
    // if (ret == 0) {
    //     // buffer->SetSize(rgbaSize);
    //     buffer->SetEsFrameSize(rgbaSize_);
    // } else {
    //     buffer->SetEsFrameSize(0);
    //     CAMERA_LOGI("CodecNode::YUV420ToRGBA8888WithNeon memcpy_s buffer  fail");
    // }
    // return;
}*/

// int CodecNode::sprd_jpeg_mem_alloc(uint32_t width, uint32_t height, void* data)
// {
//     struct sprd_jpeg_context *jpeg_cxt_ptr = &g_sprd_jpeg_cxt_ptr;
//     uint32_t yuvsize = width * height * 3 / 2;
//     /*jpeg_cxt_ptr->input_y_pmem_hp = new MemIon("/dev/ion",
//             (jpg_uint)yuvsize,
//             MemIon::NO_CACHING, ION_HEAP_ID_MASK_SYSTEM);*/
//     jpeg_cxt_ptr->input_y_pmem_hp = new MemDmabuf2((size_t)yuvsize, true, "system");

//     if ((jpeg_cxt_ptr->input_y_pmem_fd = jpeg_cxt_ptr->input_y_pmem_hp->getHeapID()) < 0) {
//         CAMERA_LOGE("failed to alloc input_y pmem buffer.\n");
//         return -1;
//     }

//     jpeg_cxt_ptr->input_y_virtual_addr = (unsigned char*)jpeg_cxt_ptr->input_y_pmem_hp->getBase();

//     CAMERA_LOGI("new yuv_buf_vir %{public}p", jpeg_cxt_ptr->input_y_virtual_addr);

//     memcpy_s((void *)jpeg_cxt_ptr->input_y_virtual_addr, yuvsize, data, yuvsize);

//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/03 start
//     //jpeg_cxt_ptr->jpg_pmem_hp = new MemIon("/dev/ion",
//     //                                      (jpg_uint)yuvsize, /*0,(1<<31)|ION_HEAP_ID_MASK_SYSTEM);*/
//     //                                      MemIon::NO_CACHING, ION_HEAP_ID_MASK_SYSTEM);
//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/03 end

//     jpeg_cxt_ptr->jpg_pmem_hp = new MemDmabuf2((size_t)yuvsize, true, "system");

//     if ((jpeg_cxt_ptr->input_jpg_pmem_fd = jpeg_cxt_ptr->jpg_pmem_hp->getHeapID() )< 0) {
//         CAMERA_LOGE("failed to alloc output_y pmem buffer.\n");
//         return -1;
//     }

//     jpeg_cxt_ptr->jpg_virtual_addr = (unsigned char*)jpeg_cxt_ptr->jpg_pmem_hp->getBase();

//     return 0;
// }

// int CodecNode::sprd_jpg_mem_release(void)
// {
//     struct sprd_jpeg_context *jpeg_cxt_ptr = &g_sprd_jpeg_cxt_ptr;
//     if (jpeg_cxt_ptr->input_y_pmem_hp != NULL)
//     {
//         jpeg_cxt_ptr->input_y_pmem_hp.clear();
//         jpeg_cxt_ptr->input_y_pmem_hp = NULL;
//     }
//     if (jpeg_cxt_ptr->jpg_pmem_hp != NULL)
//     {
//         jpeg_cxt_ptr->jpg_pmem_hp.clear();
//         jpeg_cxt_ptr->jpg_pmem_hp = NULL;
//     }
//     return 0;
// }

// void CodecNode::sprd_jpeg_evt_cb(enum jpg_jpeg_evt evt, void* data, void*privdata)
// {
//     if (NULL == data || CMR_EVT_JPEG_BASE != (CMR_EVT_JPEG_BASE & evt)) {
//         CAMERA_LOGE("err, param, 0x%lx 0x%{public}x\n", (jpg_uint)data, evt);
//         return;
//     }
//     CAMERA_LOGI("evt 0x%{public}x, handle 0x%lx\n", evt, (jpg_uint)privdata);

//     switch (evt) {
//     case CMR_JPEG_ENC_DONE:
//     {
//         struct jpeg_enc_cb_param *enc_cb_param = (struct jpeg_enc_cb_param *)data;
//         jpeg_length = enc_cb_param->stream_size;
//     }
//     CAMERA_LOGI("CMR_JPEG_ENC_DONE\n");
//     break;
//     case CMR_JPEG_DEC_DONE:
//     case CMR_JPEG_ENC_ERR:
//     case CMR_JPEG_DEC_ERR:
//     default:
//         CAMERA_LOGE("err, don't support evt 0x%{public}x\n", evt);
//     }
// }

static void Yuv420_Rot_Right_90(u_char* dst, u_char* src, int width, int height)
{
    int size = width * height;
    int pos = 0;
    int n = 0;

    // Copy y
    for(int j = 0; j < width; j++) {
        pos = size;
        for(int i = 0; i < height; i++) {
            pos -= width;
            dst[n] = src[pos + j];
            n++;
        }
    }

    // Copy uv
    int hwidth = width >> 1;
    int hheight = height >> 1;

    u_char* temp = src + size;

    for(int j = 0; j < width; j += 2) {
        pos = width * hheight;
        for(int i = 0; i < hheight; i++) {
            pos -= width;
            dst[n] = temp[pos + j];
            dst[n+1] = temp[pos + j + 1];
            n += 2;
        }
    }
}

static void Yuv420_Rot_left_90(u_char* dst, u_char* src, int width, int height)
{
    int size = width * height;
    int pos = 0;
    int n = 0;

    // Copy y
    for(int j = 0; j < width; j++) {
        pos = 0;
        for(int i = 0; i < height; i++) {
            pos += width;
            dst[n] = src[pos - j - 1];
            n++;
        }
    }

    // Copy uv
    int hwidth = width >> 1;
    int hheight = height >> 1;

    u_char* temp = src + size;

    for(int j = 0; j < width; j += 2) {
        pos = 0;
        for(int i = 0; i < hheight; i++) {
            pos += width;
            dst[n] = temp[pos - j - 2];
            dst[n+1] = temp[pos - j - 1];
            n += 2;
        }
    }
}

static void Yuv420_Rot_180(u_char* dst, u_char* src, int width, int height)
{
    int size = width * height;
    int pos = 0;
    int n = 0;

    // Copy y
    pos = size;
    for(int j = 0; j < height; j++) {
        for(int i = 0; i < width; i++) {
            dst[n] = src[pos - i - 1];
            n++;
        }
        pos -= width;
    }

    // Copy uv
    int hwidth = width >> 1;
    int hheight = height >> 1;

    u_char* temp = src + size;
    pos = width * hheight ;
    for(int j = 0; j < hheight; j++) {
        for(int i = 0; i < width; i += 2) {
            // dst[n] = temp[pos - i - 1];
            // dst[n + 1] = temp[pos - i - 2];
            dst[n + 1] = temp[pos - i - 1];
            dst[n] = temp[pos - i - 2];
            n += 2;
        }
        pos -= width;
    }
}

static void Yuv420sp_Rot_180(u_char* dst, u_char* src, int width, int height)
{
    int size = width * height;
    int pos = 0;
    int n = 0;

    // Copy y
    pos = size;
    for(int j = 0; j < height; j++) {
        for(int i = 0; i < width; i++) {
            dst[n] = src[pos - i - 1];
            n++;
        }
        pos -= width;
    }

    // Copy uv
    int hwidth = width >> 1;
    int hheight = height >> 1;

    u_char* temp = src + size;
    pos = width * hheight ;
    for(int j = 0; j < hheight; j++) {
        for(int i = 0; i < width; i += 2) {
            dst[n + 1] = temp[pos - i - 1];
            dst[n] = temp[pos - i - 2];
            n += 2;
        }
        pos -= width;
    }
}

static void Yuv420_Rot_HMirror(u_char* dst, u_char* src, int width, int height)
{
    int size = width * height;
    int pos = 0;
    int n = 0;

    // Copy y
    pos = 0;
    for(int j = 0; j < height; j++) {
        for(int i = width; i > 0; i--) {
            dst[n] = src[pos + i - 1];
            n++;
        }
        pos += width;
    }

    // Copy uv
    int hwidth = width >> 1;
    int hheight = height >> 1;

    u_char* temp = src + size;
    pos = 0;
    for(int j = 0; j < hheight; j++) {
        for(int i = width; i > 0; i -= 2) {
            dst[n] = temp[pos + i - 2];
            dst[n+1] = temp[pos + i - 1];
            n += 2;
        }
        pos += width;
    }
}

static void Yuv420_Rot_VMirror(u_char* dst, u_char* src, int width, int height)
{
    int size = width * height;
    int pos = size;
    int n = 0;

    // Copy y
    for(int j = 0; j < height; j++) {
        pos -= width;
        for(int i = 0; i < width; i++) {
            dst[n] = src[pos + i];
            n++;
        }
    }

    // Copy uv
    int hwidth = width >> 1;
    int hheight = height >> 1;

    u_char* temp = src + size;
    pos = width * hheight;
    for(int j = 0; j < hheight; j++) {
        pos -= width;
        for(int i = 0; i < width; i += 2) {
            // dst[n] = temp[pos + i + 1];
            // dst[n + 1] = temp[pos + i];
            dst[n] = temp[pos + i];
            dst[n + 1] = temp[pos + i + 1];
            n += 2;
        }
    }
}

struct CodecMetadataTag {
    std::string cameraId1 = "lcam001";
    CameraId cameraId2 = CAMERA_FIRST;
};

const CodecMetadataTag g_codecMapCameraId[] = {
    { "lcam001", CAMERA_FIRST },
    { "lcam002", CAMERA_SECOND },
    { "lcam003", CAMERA_THIRD },
    { "lcam004", CAMERA_FOURTH },
    { "lcam005", CAMERA_FIFTH },
    { "lcam006", CAMERA_SIXTH }
};

CameraId CodecNode::ConvertCameraId(const std::string &cameraId)
{
    for (auto cameraID : g_codecMapCameraId) {
        if (cameraID.cameraId1 == cameraId) {
            return cameraID.cameraId2;
        }
    }
    return CAMERA_FIRST;
}

RetCode CodecNode::ConfigJpegOrientation(common_metadata_header_t* data)
{
    camera_metadata_item_t entry;
    int ret = FindCameraMetadataItem(data, OHOS_JPEG_ORIENTATION, &entry);
    if (ret != 0 || entry.data.i32 == nullptr) {
        CAMERA_LOGI("tag OHOS_JPEG_ORIENTATION not found");
        return RC_OK;
    }

    int32_t ohosRotation = *entry.data.i32;
    if (ohosRotation == OHOS_CAMERA_JPEG_ROTATION_0) {
        jpegRotation_ = 0;
    } else if (ohosRotation == OHOS_CAMERA_JPEG_ROTATION_90) {
        jpegRotation_ = 90;
    } else if (ohosRotation == OHOS_CAMERA_JPEG_ROTATION_180) {
        jpegRotation_ = 180;
    } else {
        jpegRotation_ = 270;
    }
    return RC_OK;
}

RetCode CodecNode::ConfigJpegQuality(common_metadata_header_t* data)
{
    camera_metadata_item_t entry;
    int ret = FindCameraMetadataItem(data, OHOS_JPEG_QUALITY, &entry);
    if (ret != 0) {
        CAMERA_LOGI("tag OHOS_JPEG_QUALITY not found");
        return RC_OK;
    }

    const int HIGH_QUALITY_JPEG = 100;
    const int MIDDLE_QUALITY_JPEG = 95;
    const int LOW_QUALITY_JPEG = 85;

    CAMERA_LOGI("OHOS_JPEG_QUALITY is = %{public}d", static_cast<int>(entry.data.u8[0]));
    if (*entry.data.i32 == OHOS_CAMERA_JPEG_LEVEL_LOW) {
        jpegQuality_ = LOW_QUALITY_JPEG;
    } else if (*entry.data.i32 == OHOS_CAMERA_JPEG_LEVEL_MIDDLE) {
        jpegQuality_ = MIDDLE_QUALITY_JPEG;
    } else if (*entry.data.i32 == OHOS_CAMERA_JPEG_LEVEL_HIGH) {
        jpegQuality_ = HIGH_QUALITY_JPEG;
    } else {
        jpegQuality_ = HIGH_QUALITY_JPEG;
    }
    return RC_OK;
}

RetCode CodecNode::Config(const int32_t streamId, const CaptureMeta& meta)
{
    if (meta == nullptr) {
        CAMERA_LOGE("meta is nullptr");
        return RC_ERROR;
    }

    common_metadata_header_t* data = meta->get();
    if (data == nullptr) {
        CAMERA_LOGE("data is nullptr");
        return RC_ERROR;
    }

    RetCode rc = ConfigJpegOrientation(data);

    rc = ConfigJpegQuality(data);
    return rc;
}

// static int UnisocJpegEncodec(struct jpg_op_mean& mean, struct yuvbuf_frm& src, struct yuvbuf_frm& dst, std::shared_ptr<IBuffer>& buffer)
// {

// }

void* CodecNode::DlOpenJpegWrapperLib()
{
        CAMERA_LOGD("[tj] dlopen /vendor/soc_platform/lib64/libsprd_jpegenc_wrapper.z.so enter");
        jpeghandler = dlopen("/vendor/soc_platform/lib64/libsprd_jpegenc_wrapper.z.so", RTLD_LAZY);
        if (jpeghandler == nullptr) {
            CAMERA_LOGE("failed to dlopen  /vendor/soc_platform/lib64/libsprd_jpegenc_wrapper.z.so, %{public}s", dlerror());
            return nullptr;
        }
        CAMERA_LOGD("[tj] dlopen /vendor/soc_platform/lib64/libsprd_jpegenc_wrapper.z.so jpeghandler = %{public}p", jpeghandler);
    return jpeghandler;
}


void CodecNode::Yuv420ToJpegWithUnisoc(std::shared_ptr<IBuffer>& buffer)
{
    DlOpenJpegWrapperLib();
    if (jpeghandler == nullptr) {
        CAMERA_LOGE("failed to dlopen  /vendor/soc_platform/lib64/libsprd_jpegenc_wrapper.z.so, jpeghandler == nullptr");
        return;
    } else {
        typedef int JpegEncodecFunc(struct jpg_op_mean&, struct yuvbuf_frm&, struct yuvbuf_frm&, void*);
        JpegEncodecFunc* jpegencodecfunc = (JpegEncodecFunc*) dlsym(jpeghandler, "UnisocJpegEncodecFunc");
        const char* dlsym_error = dlerror();
        if (dlsym_error) {
            CAMERA_LOGE("Cannot load symbol UnisocJpegEncodecFunc, %{public}s", dlerror());
            goto end;
        }
        CAMERA_LOGD("dlsym UnisocJpegEncodecFunc jpeghandler = %{public}p,jpegencodecfunc= %{public}p", jpeghandler, jpegencodecfunc);
        if (jpegencodecfunc == nullptr) {
            CAMERA_LOGE("Cannot load symbol UnisocJpegEncodecFunc, %{public}s", dlerror());
            goto end;
        }
        struct jpg_op_mean mean;
        struct yuvbuf_frm src;
        struct yuvbuf_frm dst;
        mean.slice_height = 0 ;
        mean.slice_mode = 0;
        mean.is_thumb = 0;
        // HS03 code for P210926-01511 by yinshanwen at 2021/10/08 start
        mean.is_sync = 1;
        mean.quality_level = 100;
        mean.mirror = 0;
        mean.flip = 0;
        mean.rotation = 0;
        CameraId cameraId = ConvertCameraId(cameraId_);
        if (cameraId == CAMERA_FIRST) {
            mean.rotation = 1;
        } else {
            mean.mirror = 0;
            mean.flip = 1;
            mean.rotation = 1;
        }
        src.fmt = JPEGENC_YUV_420;
        uint32_t width = buffer->GetWidth();
        uint32_t height = buffer->GetHeight();
        src.size.width = width;
        src.size.height = height;
        src.addr_phy.addr_y = 0;
        src.addr_phy.addr_u = width * height;
        // src->addr_vir.addr_y=(jpg_uint)(jpeg_cxt_ptr->input_y_virtual_addr);
        // src->addr_vir.addr_u=(jpg_uint)(src->addr_vir.addr_y + width * height);
        // src->fd = jpeg_cxt_ptr->input_y_pmem_fd;
        src.data_end.y_endian = 1;
        src.data_end.uv_endian= 2;
        // MemDmabuf2::InvalidBuffer(src->fd);
        dst.addr_phy.addr_y =  0;
        // dst->addr_vir.addr_y =(jpg_uint)(jpeg_cxt_ptr->jpg_virtual_addr);
        // dst->fd = jpeg_cxt_ptr->input_jpg_pmem_fd;
        // HS03 code for P210926-01511 by yinshanwen at 2021/10/03 start
        dst.buf_size = width * height * 3 / 2;
        // HS03 code for P210926-01511 by yinshanwen at 2021/10/03 end
        if(mean.rotation == 0)
        {
            dst.size.width = width;
            dst.size.height = height;
        } else {
            dst.size.width = height;
            dst.size.height = width;
        }
    
        // 使用动态库中的函数创建对象并调用方法
        int jpeg_length = 0;
        int ret = jpegencodecfunc(mean, src, dst, buffer->GetVirAddress());
        if (ret != 0) {
            buffer->SetSize(jpeg_length);
            buffer->SetEsFrameSize(jpeg_length);
            CAMERA_LOGE("jpegencodecfunc, ret code = %{public}d", ret);
        } else {
            jpeg_length = dst.buf_size;
            if(jpeg_length != 0)
            {
                CAMERA_LOGE("buf_vir 0x%lx size %{public}d\n", dst.addr_vir.addr_y,jpeg_length);
                buffer->SetSize(jpeg_length);
                buffer->SetEsFrameSize(jpeg_length);
                // memcpy_s(buffer->GetVirAddress(), jpeg_length, (void *)(dst->addr_vir.addr_y), jpeg_length);
            } else {
                buffer->SetSize(jpeg_length);
                buffer->SetEsFrameSize(jpeg_length);
                CAMERA_LOGE("jpeg_length = 0, error!\n");
            }
        }
    }
end:
    if (jpeghandler != nullptr) {
        CAMERA_LOGD("[tj] close jpg handler!\n");
        dlclose(jpeghandler);
        jpeghandler = nullptr;
    }
}

// void CodecNode::Yuv420ToJpegWithUnisoc(std::shared_ptr<IBuffer>& buffer)
// {
//     uint32_t i = 0;
//     jpeg_length = 0;
//     struct sprd_jpeg_context *jpeg_cxt_ptr = &g_sprd_jpeg_cxt_ptr;

//     struct jpeg_codec_caller_handle  oem_handle ;
//     struct yuvbuf_frm *src =  (struct yuvbuf_frm*)malloc(sizeof(struct yuvbuf_frm));
//     struct yuvbuf_frm *dst =(struct yuvbuf_frm*)malloc(sizeof(struct yuvbuf_frm));
//     struct jpg_op_mean *mean=(struct jpg_op_mean*)malloc(sizeof(struct jpg_op_mean));

//     sprd_jpeg_init( &oem_handle,sprd_jpeg_evt_cb);

//     uint32_t width = buffer->GetWidth();
//     uint32_t height = buffer->GetHeight();

//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/09 start
//     int result_sprd_jpeg_mem_alloc = sprd_jpeg_mem_alloc(width, height, buffer->GetVirAddress());
//     if (result_sprd_jpeg_mem_alloc == -1) {
//         CAMERA_LOGE("sprd_jpeg_mem_alloc error!\n");
//         free(src);
//         free(dst);
//         free(mean);
//         sprd_jpg_mem_release();
//         return ;
//     }
//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/09 end

//     mean->slice_height = 0 ;
//     mean->slice_mode = 0;
//     mean->is_thumb = 0;
//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/08 start
//     mean->is_sync = 1;
//     mean->quality_level = 100;
//     mean->mirror = 0;
//     mean->flip = 0;
//     mean->rotation = 0;
//     CameraId cameraId = ConvertCameraId(cameraId_);
//     if (cameraId == CAMERA_FIRST) {
//         mean->rotation = 1;
//     } else {
//         mean->mirror = 0;
//         mean->flip = 1;
//         mean->rotation = 1;
//     }

//     src->fmt = JPEGENC_YUV_420;
//     src->size.width = width;
//     src->size.height = height;
//     src->addr_phy.addr_y = 0;
//     src->addr_phy.addr_u = width * height;
//     src->addr_vir.addr_y=(jpg_uint)(jpeg_cxt_ptr->input_y_virtual_addr);
//     src->addr_vir.addr_u=(jpg_uint)(src->addr_vir.addr_y + width * height);
//     src->fd = jpeg_cxt_ptr->input_y_pmem_fd;
//     src->data_end.y_endian = 1;
//     src->data_end.uv_endian= 2;

//     //MemIon::Invalid_ion_buffer(src->fd);
//     MemDmabuf2::InvalidBuffer(src->fd);

//     dst->addr_phy.addr_y =  0;
//     dst->addr_vir.addr_y =(jpg_uint)(jpeg_cxt_ptr->jpg_virtual_addr);
//     dst->fd = jpeg_cxt_ptr->input_jpg_pmem_fd;
//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/03 start
//     dst->buf_size = width * height * 3 / 2;
//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/03 end
//     if(mean->rotation == 0)
//     {
//         dst->size.width = width;
//         dst->size.height = height;
//     } else {
//         dst->size.width = height;
//         dst->size.height = width;
//     }

//     CAMERA_LOGI("src phy addr 0x%lx 0x%lx src vir addr 0x%lx 0x%lx\n", src->addr_phy.addr_y, src->addr_phy.addr_u,
//          src->addr_vir.addr_y, src->addr_vir.addr_u);
//     CAMERA_LOGI("src fd %{public}d, dst fd %{public}d \n",src->fd,dst->fd);
//     CAMERA_LOGI("dst phr addr 0x%lx vir addr 0x%lx\n", dst->addr_phy.addr_y, dst->addr_vir.addr_y);
//     CAMERA_LOGI("src size %{public}d %{public}d\n", src->size.width, src->size.height);
//     CAMERA_LOGI("out size %{public}d %{public}d\n", dst->size.width, dst->size.height);

//     struct jpeg_enc_cb_param cb_param;
//     sprd_jpg_encode(&oem_handle, src, dst, mean, &cb_param);
//     jpeg_length = dst->buf_size;
//     sprd_jpeg_deinit(&oem_handle);

//     if(jpeg_length != 0)
//     {
//         CAMERA_LOGE("buf_vir 0x%lx size %{public}d\n", dst->addr_vir.addr_y,jpeg_length);
//         buffer->SetSize(jpeg_length);
//         buffer->SetEsFrameSize(jpeg_length);
//         memcpy_s(buffer->GetVirAddress(), jpeg_length, (void *)(dst->addr_vir.addr_y), jpeg_length);
//     }
//     else{
//         CAMERA_LOGE("jpeg_length = 0, error!\n");
//     }
// //	if(mean->is_sync == 1)
// //	{
// //		FILE *fp = fopen("data/sync11.jpg", "wb");
// //			
// //		CAMERA_LOGI("buf_vir 0x%lx size %{public}d\n", dst->addr_vir.addr_y,dst->buf_size);
// //
// //		if(dst->buf_size> 0 && dst->addr_vir.addr_y && fp)
// //		{
// //			fwrite((void *)( dst->addr_vir.addr_y ),1,dst->buf_size,fp);
// //			CAMERA_LOGI("fwrite\n");
// //		}
// //		if(fp != NULL)
// //		{
// //			fclose(fp);
// //		}
// //	}
//     CAMERA_LOGI("finish out\n");
//     free(src);
//     free(dst);
//     free(mean);
//     // HS03 code for P210926-01511 by yinshanwen at 2021/10/08 end
//     sprd_jpg_mem_release();
//     return ;
// }

int CodecNode::Yuv420ToH264WithUnisoc(std::shared_ptr<IBuffer>& buffer, uint32_t& frameSize)
{
    //drop the design scheme about gitee camera_hsot scale_node;
    // std::map<int32_t, uint8_t*> sizeVirMap = bufferPool_->getSFBuffer(bufferPool_->GetForkBufferId());
    // if (sizeVirMap.empty()) {
    //     CAMERA_LOGE("CodecNode::Yuv420ToH264WithUnisoc sizeVirMap buffer == nullptr");
    //     return -1;
    // }
    // uint8_t* temp = sizeVirMap.begin()->second;

    uint32_t width = buffer->GetWidth();
    uint32_t height = buffer->GetHeight();
    unsigned int size = width * height * 3 / 2;
    if (bufferRotate_ == NULL) {
        bufferRotate_ = (u_char* )malloc(size);
        if(!bufferRotate_) {
            CAMERA_LOGE("malloc memery error!");
            return -1;
        }
    }
    CameraId cameraId = ConvertCameraId(cameraId_);
    if (cameraId == CAMERA_FIRST) {
        // Yuv420_Rot_180((u_char*)buffer->GetVirAddress(), (u_char*)temp, width, height);
        Yuv420_Rot_180(bufferRotate_, (u_char*)buffer->GetVirAddress(), width, height);
    } else {
        // Yuv420_Rot_VMirror((u_char*)buffer->GetVirAddress(), (u_char*)temp, width, height);
        Yuv420_Rot_VMirror(bufferRotate_, (u_char*)buffer->GetVirAddress(), width, height);
    }
    int ret = memcpy_s((void*)buffer->GetVirAddress(), size, (void*)bufferRotate_, size);
    if (ret != 0) {
        CAMERA_LOGE("copy memery error!");
        return -1;
    }

    if (h264Encoder != nullptr) {
        MMInputParams input;
        memset(&input, 0, sizeof(MMInputParams));
        input.org_width = 0;
        input.org_height = 0;
        input.width = buffer->GetWidth();
        input.height = buffer->GetHeight();
        input.format = H264;
        input.framerate = 30;
        input.max_key_interval = 10;
        input.cbr = 1;
        input.bitrate = 3000000; //512
        input.qp = 8;
        input.frames = 0;
        input.eis = 0;
        input.yuv_format = MMENC_YUV420SP_NV21;//MMENC_YUV420SP_NV12;
        input.vsp = MMENC_VSP;
        input.fbc_mode = FBC_NONE;

        if (input.eis == 0) {
            input.org_height = input.height;
            input.org_width = input.width;
        }

        CAMERA_LOGI("Yuv420ToH264WithUnisoc:: h264Encoder status is %{public}d, codecnode addr is %{public}p", status.load(), this);
        if (status == 0) {//0, START
            status = 1;//1, ENCODING
            if (h264Encoder->vsp_start(&input, (char*)(buffer->GetVirAddress()), frameSize) < 0) {
                CAMERA_LOGE("CodecNode:: h264Encoder.vsp_start err");
                // h264Encoder.vsp_stop();
                return -1;
            }
            startflag = 1;
        }
        int type = 0;
        int ret = h264Encoder->vsp_enc(&input, (char*)(buffer->GetVirAddress()), frameSize, type);
        if (ret == 0) {
            if (type == 0) {
                buffer->SetEsKeyFrame(1);
                startflag = 0;
            } else {
                if(startflag == 1) {
                    buffer->SetBufferStatus(CAMERA_BUFFER_STATUS_INVALID);
                }
                buffer->SetEsKeyFrame(0);
            }
            CAMERA_LOGE("CodecNode:: h264Encoder.vsp_start startflag=%{public}d key=%{public}d,SetEsKeyFrame=%{public}d", startflag, type, buffer->GetEsFrameInfo().isKey);
        } else {
            buffer->SetBufferStatus(CAMERA_BUFFER_STATUS_INVALID);
            buffer->SetEsKeyFrame(0);
        }
        return ret;
    } else {
        CAMERA_LOGE("CodecNode::Yuv420ToH264WithUnisoc h264Encoder is null");
        return -1;
    }
}

static uint64_t GetPts()
{
    constexpr uint32_t SEC_TO_NS = 1000000000;
    struct timespec timestamp = {0, 0};
    clock_gettime(CLOCK_MONOTONIC, &timestamp);
    uint64_t time = (uint64_t)timestamp.tv_sec * SEC_TO_NS + (uint64_t)timestamp.tv_nsec;
    return time;
}

void CodecNode::DeliverBuffer(std::shared_ptr<IBuffer>& buffer)
{
    if (buffer == nullptr) {
        CAMERA_LOGE("CodecNode::DeliverBuffer frameSpec is null");
        return;
    }

    int32_t id = buffer->GetStreamId();
    CAMERA_LOGD("CodecNode::DeliverBuffer StreamId %{public}d, encode type : %{public}d", id, buffer->GetEncodeType());
    if (buffer->GetEncodeType() == VDI::Camera::V1_0::ENCODE_TYPE_JPEG) {
        if (buffer->GetBufferStatus() == CAMERA_BUFFER_STATUS_OK) {
            Yuv420ToJpegWithUnisoc(buffer);
        }
        CAMERA_LOGI("CodecNode::node codec enter jpeg,%{public}d", (int)buffer->GetSize());
    // }else if (buffer->GetEncodeType() == ENCODE_TYPE_YUV) {
    }else if (buffer->GetEncodeType() == 4) {
        buffer->SetEsFrameSize(8294400);
        CAMERA_LOGI("CodecNode::node codec enter yuv,%{public}d", (int)buffer->GetSize());
    } else if (buffer->GetEncodeType() == VDI::Camera::V1_0::ENCODE_TYPE_H264) {
        nodestatus = 1;
        uint32_t frameSize = 0;
        Yuv420ToH264WithUnisoc(buffer, frameSize);
        buffer->SetEsFrameSize(frameSize);
        buffer->SetEsTimestamp(GetPts());
    } else {
        CAMERA_LOGI("CodecNode::node buffer format = %{public}d", buffer->GetFormat());
        int yuv_length = buffer->GetWidth() * buffer->GetHeight() * 3 / 2;
        buffer->SetEsFrameSize(yuv_length);
        CameraId cameraId = ConvertCameraId(cameraId_);
        if (cameraId != CAMERA_FIRST) {
            if (bufferRotate_ == NULL) {
                bufferRotate_ = (u_char* )malloc(yuv_length);
                if(!bufferRotate_) {
                    return;
                }
            }
            Yuv420sp_Rot_180(bufferRotate_, (u_char*)buffer->GetVirAddress(), buffer->GetWidth(), buffer->GetHeight());
            memcpy_s((void*)buffer->GetVirAddress(), buffer->GetSize(), (void*)bufferRotate_, yuv_length);
        }
    }

    std::vector<std::shared_ptr<IPort>> outPutPorts = GetOutPorts();
    for (auto& it : outPutPorts) {
        if (it->format_.streamId_ == id) {
            it->DeliverBuffer(buffer);
            CAMERA_LOGI("CodecNode deliver buffer streamid = %{public}d", it->format_.streamId_);
            return;
        }
    }
}

RetCode CodecNode::Capture(const int32_t streamId, const int32_t captureId)
{
    CAMERA_LOGV("CodecNode::Capture");
    return RC_OK;
}

RetCode CodecNode::CancelCapture(const int32_t streamId)
{
    int ret = RC_OK;
    CAMERA_LOGI("CodecNode::CancelCapture streamid = %{public}d", streamId);
    if (nodestatus == 1) {
        if (status == 1) {//1, ENCODING
            status = 0;//0, START
            CAMERA_LOGI("CodecNode::CancelCapture 1 streamid = %{public}d", streamId);
            if (h264Encoder != nullptr) {
                h264Encoder->vsp_stop();
            } else {
                CAMERA_LOGE("CodecNode::CancelCapture h264Encoder is null");
                ret = -1;
            }
            CAMERA_LOGI("CodecNode::CancelCapture 2 streamid = %{public}d", streamId);
        }
        nodestatus = 0;
    }
    return ret;
}

REGISTERNODE(CodecNode, {"Codec"})
} // namespace OHOS::Camera
